package cn.qianxun.meta.safevalue.service.impl;

import cn.easyes.core.conditions.LambdaEsQueryWrapper;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.qianxun.meta.common.core.utils.StringUtils;
import cn.qianxun.meta.safevalue.dto.AddSysSafeValueParamDTO;
import cn.qianxun.meta.safevalue.entity.SysSafeValueParam;
import cn.qianxun.meta.safevalue.esmapper.SafeValueLogMapper;
import cn.qianxun.meta.safevalue.mapper.SysSafeValueParamMapper;
import cn.qianxun.meta.safevalue.service.ISysSafeValueParamService;
import cn.qianxun.meta.safevalue.vo.SafeValueParamItemVO;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.qianxun.meta.common.core.constant.SafeValConstants;
import cn.qianxun.meta.common.log.changeField.vo.SafeValueLogVO;
import cn.qianxun.meta.log.api.dto.SaveSafeValueLog;
import cn.qianxun.meta.safevalue.vo.SafeValTotalNumVO;
import cn.qianxun.meta.safevalue.vo.SafeValueItemValVO;
import cn.qianxun.meta.safevalue.vo.SafeValueParamDetailVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 安全值参数配置 服务实现类
 * </p>
 *
 * @author fuzhilin
 * @since 2023-09-07 04:26:40
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class SysSafeValueParamServiceImpl extends ServiceImpl<SysSafeValueParamMapper, SysSafeValueParam> implements ISysSafeValueParamService {
    private final SafeValueLogMapper safeValueLogMapper;


    @Override
    public SafeValueParamDetailVO detail() {
        SafeValueParamDetailVO vo = new SafeValueParamDetailVO();
        SysSafeValueParam po = baseMapper.selectOne(new LambdaQueryWrapper<SysSafeValueParam>().last("limit 1"));
        if (po != null) {
            BeanUtil.copyProperties(po, vo, "content");
            //设置content
            List<SafeValueParamItemVO> content = JSON.parseArray(po.getContent(), SafeValueParamItemVO.class);
            vo.setContent(content);
        }
        return vo;
    }

    @Override
    public void saveSafeValueParam(AddSysSafeValueParamDTO dto) {
        //保存
        if (StringUtils.isNotEmpty(dto.getId())) {
            SysSafeValueParam safeValueParam = baseMapper.selectById(dto.getId());
            BeanUtil.copyProperties(dto, safeValueParam);
            //设置content
            safeValueParam.setContent(JSON.toJSONString(dto.getContent()));
            baseMapper.updateById(safeValueParam);
        } else {
            SysSafeValueParam safeValueParam = new SysSafeValueParam();
            BeanUtil.copyProperties(dto, safeValueParam);
            //设置content
            safeValueParam.setCreateTime(new Date());
            safeValueParam.setContent(JSON.toJSONString(dto.getContent()));
            baseMapper.insert(safeValueParam);
        }
    }

    @Override
    public SafeValTotalNumVO getSafeValCount() {
        SafeValTotalNumVO valTotalNumVO = new SafeValTotalNumVO();
        SaveSafeValueLog safeValueLog = safeValueLogMapper.selectOne(new LambdaEsQueryWrapper<SaveSafeValueLog>().eq(SaveSafeValueLog::getBusinessType, 0));
        if (StringUtils.isNotNull(safeValueLog)) {
            valTotalNumVO.setScore(safeValueLog.getScore());
            BigDecimal change = new BigDecimal(safeValueLog.getScore()).subtract(new BigDecimal(StringUtils.isEmpty(safeValueLog.getOldScore()) ? "0" : safeValueLog.getOldScore()));
            valTotalNumVO.setChange(String.valueOf(change));
            double score = Double.parseDouble(safeValueLog.getScore());
            if (score >= 80.00 && score <= 100.00) {
                valTotalNumVO.setLevel("high");
            } else if (score >= 60.00 && score < 80.00) {
                valTotalNumVO.setLevel("middle");
            } else if (score < 60.00) {
                valTotalNumVO.setLevel("low");
            }
        }
        return valTotalNumVO;
    }


    /**
     * 创建安全值
     */
    public void createSafeValue() {
        SysSafeValueParam safeValueParam = baseMapper.selectOne(new LambdaQueryWrapper<SysSafeValueParam>().last("limit 1"));
        if (StringUtils.isNull(safeValueParam)) {
            return;
        }
        //获取配置条目
        /*List<SafeValueParamItemVO> list = JSON.parseArray(safeValueParam.getContent(), SafeValueParamItemVO.class);
        if (CollectionUtil.isEmpty(list)) {
            return;
        }*/

        //老安全值
        /*String oldScore = "0";
        SaveSafeValueLog safeValueLog = safeValueLogMapper.selectOne(new LambdaEsQueryWrapper<SaveSafeValueLog>().eq(SaveSafeValueLog::getBusinessType, 0).limit(1));
        if (StringUtils.isNotNull(safeValueLog) && StringUtils.isNotEmpty(safeValueLog.getOldScore())) {
            oldScore = safeValueLog.getOldScore();
        }*/
        //先删除老数据
        safeValueLogMapper.delete(new LambdaEsQueryWrapper<>());
        //新增
       /* creCusSafeVal(id, list, oldScore);//总安全值
        creCusSafeValByArea(id, list);//分区域安全值
        creCusSafeValByIndustry(id, list);//分行业安全值*/
        // 发布事件保存数据库
        /*List<SafeValueLogVO> valueLogs = new ArrayList<>();
        valueLogs.add(creSafeVal(list, oldScore));
        SpringUtils.context().publishEvent(new SafeValueLogEvent().setSafeValueLogList(valueLogs));*/
        //创建web安全值
        log.info("创建web安全值");
        //webScanProvider.createWebSafeValue(safeValueParam.getContent());
    }

    /**
     * 创建新的安全值
     *
     * @param list     list
     * @param oldScore oldScore
     */
    public SafeValueLogVO creSafeVal(List<SafeValueParamItemVO> list, String oldScore) {
        List<Double> scores = new ArrayList<>();
        //根据不同类型计算
        for (SafeValueParamItemVO vo : list) {
            String type = vo.getType();//类型
            String minLimit = vo.getMinLimit();//下限值
            Double limit = Double.valueOf(minLimit);
            List<SafeValueItemValVO> items = vo.getItems();//参数条目
            if (CollectionUtil.isEmpty(items)) {
                continue;
            }
            //漏洞
            if (SafeValConstants.SAFE_WEB_LOOPHOLE.equals(type)) {
                Map<String, Integer> map = new HashMap<>();
                Double score = getTotal(items, map, limit);
                scores.add(score);
            }
            //攻击事件
            if (SafeValConstants.SAFE_ATTACK_EVENT.equals(type)) {
                Map<String, Integer> map = new HashMap<>();
                Double score = getTotal(items, map, limit);
                scores.add(score);
            }
        }
        //计算最小值
        Double minScore = 100.00;
        if (CollectionUtil.isNotEmpty(scores)) {
            minScore = Collections.min(scores);//比较所有类型最小值
        }
        //保存总安全值
        String safeValue = String.format("%.2f", minScore);
        SafeValueLogVO safeValueLog = new SafeValueLogVO();
        safeValueLog.setScore(safeValue);
        safeValueLog.setAssetName("");
        safeValueLog.setBusinessType("0");
        safeValueLog.setCreateTime(new Date());
        safeValueLog.setOldScore(oldScore);
        return safeValueLog;
    }

    /**
     * 计算安全值-最小为下限值
     *
     * @param items items
     * @param map   map
     * @param limit limit
     * @return Double
     */
    public Double getTotal(List<SafeValueItemValVO> items, Map<String, Integer> map, Double limit) {
        double res = 100.00;//剩余分数
        for (SafeValueItemValVO o : items) {
            //类型匹配，计算扣分
            if (map.containsKey(o.getKey())) {
                Integer num = map.get(o.getKey());//总数
                Double val = Double.valueOf(o.getValue());//分值
                double count = num * val;//总扣分
                res = res - count;//剩余分数
                if (res <= limit) {
                    res = limit;//最小就是下限值
                    break;
                }
            }
        }
        return res;
    }

}
